//-----------------------------------------------------------------------------
// Bend2D - Physics Engine
// Roberto Bender <beto.bender@gmail.com>
// Description: 
// Date: 12/03/2010
//-----------------------------------------------------------------------------
#ifndef WORLD_H
#define WORLD_H

#include "rectangle.h"
#include "boundary.h"
#include "drawable.h"
#include "fastcast.h"
#include "moveable.h"
#include "durable.h"
#include "collidable.h"
#include "collideregions.h"
#include "physicforce.h"
#include "benchmarking.h"

#include <map>
#include <list>
using namespace std;

namespace bend2d
{
    class World : 
        public Drawable,
        public CollideRegions
    {
        public:
            enum eWorldFlags { eUnknownFlag, eTwoStepsIteration };

            World();
            World(const Rectangle& boundary);
            const Rectangle& GetBoundary() const;
            void SetBoundary(const Rectangle& boundary);
            void Iterate(double timeSinceLastFrame);
            void Iterated();
            void RegistryObject(FastCast* object);
            void RegistryObject(list<FastCast*> objects);
            void RegistryPhysicForce(PhysicForce* force);
            void UnRegistryObject(FastCast* object, bool destroy = false);
            void Draw();

            void Enable(eWorldFlags flag);
            void Disable(eWorldFlags flag);
            bool GetFlag(eWorldFlags flag);

            Durable::DurableList& GetDurableList() { return m_DurableList; }
            Drawable::DrawableList& GetDrawableList() { return m_DrawableList; }
            FastCast::FastCastList& GetFastCastList() { return m_FastCastList; }
            Moveable::MoveableList& GetMoveableList() { return m_MoveableList; }
            Collidable::CollidableList& GetCollidableList() { return m_CollidableList; }
            PhysicForce::PhysicForceList& GetPhysicForceList() { return m_PhysicForceList; }
            Physicable::PhysicableList& GetPhysicableList() { return m_PhysicableList; }

            double GetTimeSinceLastIteration() const;

#ifdef BEND2D_DEBUG
            void DrawNew();
#endif
        private:
            enum Boundaries { leftBound, topBound, rightBound, bottomBound };
            Rectangle m_WorldBoundary;
            Boundary* m_RealBoundary[4];
            void RecreateRealBoundary();
            
            Durable::DurableList         m_DurableList;
            Drawable::DrawableList       m_DrawableList;
            FastCast::FastCastList       m_FastCastList;

            Moveable::MoveableList       m_MoveableList;
            Collidable::CollidableList   m_CollidableList;
            PhysicForce::PhysicForceList m_PhysicForceList;
            Physicable::PhysicableList   m_PhysicableList;

            map<eWorldFlags, bool>       m_Flags;
            StopWatch                    m_IterationStopWatch;
            double                       m_TimeSinceLastFrame;
    };
}

#endif
